home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagn_r.zip / OOP.SWG / 0044_Clock on Menubar.pas < prev    next >
Pascal/Delphi Source File  |  1994-08-26  |  13KB  |  543 lines

  1. unit clocks;
  2. {$X+}  {allow discardable function results}
  3.  
  4. { Clock-on-a-menubar OOP extension to Turbo Vision apps
  5.  
  6.   Copyright (c) 1990 by Danny Thorpe
  7.  
  8.   Alarms have not been implemented.
  9. }
  10.  
  11. interface
  12. uses dos, objects, drivers, views, menus, dialogs, app, msgbox;
  13.  
  14. const  cmClockChangeDisplay = 1001;
  15.        cmClockSetAlarm = 1002;
  16.  
  17.        ClockNoSecs   = 0;
  18.        ClockDispSecs = 1;
  19.        Clock12hour   = 0;
  20.        Clock24hour   = 1;
  21.  
  22. type
  23.  
  24.      ClockDataRec = record
  25.        Format: word;
  26.        Seconds: word;
  27.        RefreshStr: String[2];
  28.        end;
  29.  
  30.  
  31.      PClockMenu = ^TClockMenu;
  32.      TClockMenu = object(TMenuBar)
  33.        ClockOptions: ClockDataRec;
  34.        Refresh: byte;
  35.        LastTime: DateTime;
  36.        TimeStr: string[10];
  37.        constructor Init(var Bounds: TRect; Amenu: PMenu);
  38.        procedure Draw;   virtual;
  39.        procedure Update; virtual;
  40.        procedure SetRefresh(Secs: integer);        virtual;
  41.        procedure SetRefreshStr( Secs: string);     virtual;
  42.        procedure ClockChangeDisplay;               virtual;
  43.        procedure HandleEvent( var Event: TEvent);  virtual;
  44.        function  FormatTimeStr(h,m,s:word):string; virtual;
  45.        end;
  46.  
  47.  
  48.  
  49.  
  50. implementation
  51.  
  52.  
  53. function LeadingZero(w : Word) : String;
  54. var
  55.   s : String;
  56. begin
  57.   Str(w:0,s);
  58.   if Length(s) = 1 then
  59.     s := '0' + s;
  60.   LeadingZero := s;
  61. end;
  62.  
  63.  
  64.  
  65. constructor TClockMenu.Init(var Bounds: TRect; AMenu: PMenu);
  66.   var Temp: PMenuBar;
  67.       ClockMenu: PMenu;
  68.       R: TRect;
  69.   begin
  70.   ClockMenu:= NewMenu(NewSubMenu('~'#0'~Clock ', hcNoContext, NewMenu(
  71.                 NewItem('~C~hange display','',0,cmClockChangeDisplay, hcNoContext,
  72.                 NewItem('Set ~A~larm','', 0, cmClockSetAlarm, hcNoContext,
  73.                 nil))),
  74.                 AMenu^.Items));
  75.                 { ^^ tack passed menubar on end of new clock menu }
  76.   ClockMenu^.Default:= AMenu^.Default;
  77.  
  78.   TMenuBar.Init(Bounds, ClockMenu);
  79.  
  80.   fillchar(LastTime,sizeof(LastTime),#$FF);   {fill with 65000's}
  81.   TimeStr:='';
  82.   ClockOptions.Format:= Clock24Hour;
  83.   ClockOptions.Seconds:= ClockDispSecs;
  84.   SetRefresh(1);
  85.   end;
  86.  
  87.  
  88.  
  89. procedure TClockMenu.Draw;
  90.   var P: PMenuItem;
  91.   begin
  92.   P:= FindItem(#0);
  93.   if P <> nil then
  94.     begin
  95.     DisposeStr(P^.Name);
  96.     P^.Name:= NewStr('~'#0'~'+TimeStr);
  97.     end;
  98.   TMenuBar.Draw;
  99.   end;
  100.  
  101.  
  102.  
  103. procedure TClockMenu.Update;
  104.   var h,m,s,hund: word;
  105.   begin
  106.     GetTime(h,m,s,hund);
  107.     if abs(s-LastTime.sec) >= Refresh then
  108.       begin
  109.       with LastTime do
  110.         begin
  111.         Hour:=h;
  112.         Min:=m;
  113.         Sec:=s;
  114.         end;
  115.       TimeStr:= FormatTimeStr(h,m,s);
  116.       DrawView;
  117.       end;
  118.   end;
  119.  
  120.  
  121.  
  122.  
  123. procedure TClockMenu.SetRefresh(Secs: integer);
  124.   begin
  125.   if Secs > 59 then
  126.     Secs := 59;
  127.   if Secs < 0 then
  128.     Secs := 0;
  129.   Refresh:= Secs;
  130.   Str(Refresh:2,ClockOptions.RefreshStr);
  131.   end;
  132.  
  133.  
  134.  
  135. procedure TClockMenu.SetRefreshStr( Secs: string);
  136.   var temp,code: integer;
  137.   begin
  138.   val(Secs, temp, code);
  139.   if code = 0 then
  140.     SetRefresh(temp);
  141.   end;
  142.  
  143.  
  144.  
  145.  
  146. procedure TClockMenu.ClockChangeDisplay;
  147.  
  148.   var
  149.     D: PDialog;
  150.     Control: PView;
  151.     Command: word;
  152.     temp,code: integer;
  153.     R: TRect;
  154.     ClockData : ClockDataRec;
  155.  
  156.   begin
  157.  
  158.   ClockData := ClockOptions;
  159.  
  160.   R.Assign(14,3,48,15);
  161.   D:= new(PDialog, Init(R, 'Clock Display'));
  162.  
  163.   R.Assign(3,3,20,5);
  164.   Control:= new(PRadioButtons, Init(R,
  165.             NewSItem('~1~2 hour',
  166.             NewSItem('~2~4 hour',
  167.             nil))));
  168.   D^.Insert(Control);
  169.  
  170.   R.Assign(3,2,20,3);
  171.   Control:= new(Plabel, Init(R, '~F~ormat', Control));
  172.   D^.Insert(Control);
  173.  
  174.   R.Assign(3,6,20,7);
  175.   Control:= new(PCheckBoxes, Init(R,
  176.             NewSItem('~S~econds',
  177.             nil)));
  178.   D^.Insert(Control);
  179.  
  180.   R.Assign(16,9,20,10);
  181.   Control:= new(PInputLine, Init(R, 2));
  182.   D^.Insert(Control);
  183.  
  184.   R.Assign(2,8,20,9);
  185.   Control:= new(PLabel, Init(R, '~R~efresh Rate', Control));
  186.   D^.Insert(Control);
  187.  
  188.   R.Assign(2,9,15,10);
  189.   Control:= new(PLabel, Init(R, '0-59 seconds', PLabel(Control)^.Link));
  190.   D^.Insert(Control);
  191.  
  192.   R.Assign(21,3,31,5);
  193.   Control:= new(PButton, Init(R, '~O~k', cmOk, bfDefault));
  194.   D^.Insert(Control);
  195.  
  196.   R.Assign(21,6,31,8);
  197.   Control:= new(PButton, Init(R, '~C~ancel', cmCancel, bfNormal));
  198.   D^.Insert(Control);
  199.  
  200.  
  201.   D^.SelectNext(False);
  202.   D^.SetData(ClockData);
  203.   repeat
  204.     Command:= Desktop^.ExecView(D);
  205.     if Command = cmOK then
  206.       begin
  207.       D^.GetData(ClockData);
  208.       val(ClockData.RefreshStr,temp,code);
  209.       if (code <> 0) or ((temp<0) or (temp>59)) then
  210.         MessageBox('Refresh rate must be between 0 and 59 seconds.',nil,
  211.            mfOKButton+mfError);
  212.       end;
  213.   until (Command = cmCancel)
  214.      or ((code=0) and ((temp>=0) and (temp<=59)));
  215.  
  216.   Dispose(D, Done);
  217.  
  218.   if Command = cmOk then
  219.     begin
  220.     ClockOptions:= ClockData;
  221.     SetRefreshStr(ClockData.RefreshStr);
  222.     end;
  223.  
  224.   { update display to reflect changes immediately }
  225.   TimeStr:= FormatTimeStr(LastTime.hour, LastTime.min, LastTime.sec);
  226.   DrawView;
  227.   end;
  228.  
  229.  
  230.  
  231.  
  232.  
  233. procedure TClockMenu.HandleEvent( var Event: TEvent);
  234.   begin
  235.   TMenuBar.HandleEvent( Event);
  236.   if Event.What = evCommand then
  237.     begin
  238.     case Event.Command of
  239.       cmClockChangeDisplay: ClockChangeDisplay;
  240.       cmClockSetAlarm: ;
  241.       end;
  242.     end;
  243.   end;
  244.  
  245.  
  246.  
  247.  
  248. function TClockMenu.FormatTimeStr(h,m,s: word): string;
  249.   var st, tail: string;
  250.   begin
  251.   tail:='';
  252.   if ClockOptions.Format = Clock24Hour then
  253.     st:= LeadingZero(h)
  254.   else
  255.     begin
  256.     if h >= 12 then
  257.       begin
  258.       tail:= 'pm';
  259.       if h>12 then
  260.         dec(h,12);
  261.       end
  262.     else
  263.       tail:= 'am';
  264.     if h=0 then h:=12;   {12 am}
  265.     str(h:0,st);    { no leading space on hours }
  266.     end;
  267.  
  268.   st:=st+':'+ LeadingZero(m);
  269.  
  270.  
  271.   if ClockOptions.Seconds = ClockDispSecs then
  272.     st:= st+':'+LeadingZero(s);
  273.  
  274.   FormatTimeStr:= st + tail;
  275.   end;
  276.  
  277.  
  278.  
  279.  
  280. end.
  281.  
  282. { ----------------------------- DEMO  ---------------------- }
  283.  
  284. program TestPlatform;
  285.  
  286. uses Objects, Drivers, Views, Menus, App,
  287.      Dos,     { for the paramcount and paramstr funcs}
  288.      Clocks;  { for the clock on the menubar object, TClockMenu }
  289.  
  290. { This generic test platform has been hooked up to the clock-on-the-menubar
  291.   object / unit.  Search for *** to find hook-up points.
  292.  
  293.   Copyright (c) 1990 by Danny Thorpe
  294. }
  295.  
  296.  
  297. const  cmNewWin =   100;
  298.        cmFileOpen = 101;
  299.  
  300.        WinCount : Integer = 0;
  301.        MaxLines = 50;
  302.  
  303.  
  304. type  PInterior = ^TInterior;
  305.       TInterior = object(TScroller)
  306.         constructor init(var Bounds: TRect; AHScrollbar, AVScrollbar: PScrollbar);
  307.         procedure Draw;  virtual;
  308.         end;
  309.  
  310.  
  311.       PDemoWindow = ^TDemoWindow;
  312.       TDemoWindow = object(TWindow)
  313.         constructor Init(WindowNo: integer);
  314.         end;
  315.  
  316.  
  317.       TMyApp = object(TApplication)
  318.         procedure InitStatusLine;  virtual;
  319.         procedure InitMenuBar;  virtual;
  320.         procedure NewWindow;
  321.         procedure HandleEvent( var Event: TEvent); virtual;
  322.         procedure Idle; virtual;
  323.         end;
  324.  
  325.  
  326. var MyApp: TMyApp;
  327.     Lines: array [0..MaxLines-1] of PString;
  328.     LineCount: Integer;
  329.  
  330.  
  331. constructor TInterior.Init(var Bounds: TRect; AHScrollbar, AVScrollbar: PScrollbar);
  332.   begin
  333.   TScroller.Init(Bounds,AHScrollbar,AVScrollbar);
  334.   Growmode := gfGrowHiX + gfGrowHiY;
  335.   Options := Options or ofFramed;
  336.   SetLimit(128,LineCount);
  337.   end;
  338.  
  339.  
  340. procedure TInterior.Draw;
  341.   var color: byte;
  342.       y,i: integer;
  343.       B: TDrawBuffer;
  344.  
  345.   begin
  346.   TScroller.Draw;
  347.   Color := GetColor($01);
  348.   for y:= 0 to Size.Y -1 do
  349.     begin
  350.     MoveChar(B,' ',Color,Size.X);
  351.     I := Delta.Y + Y;
  352.     if (I<Linecount) and (Lines[I] <> nil) then
  353.       MoveStr(B,Copy(Lines[I]^,Delta.X+1,size.x),Color);
  354.     WriteLine(0,y,size.x,1,B);
  355.     end;
  356.   end;
  357.  
  358.  
  359. procedure ReadFile;
  360.   var  F: text;
  361.        S: string;
  362.  
  363.   begin
  364.   LineCount:=0;
  365.   if paramcount = 0 then
  366.     assign(F,'clockwrk.pas')
  367.   else
  368.     assign(F,paramstr(1));
  369.   reset(F);
  370.   while not eof(F) and (linecount < maxlines) do
  371.     begin
  372.     readln(f,s);
  373.     Lines[Linecount] := NewStr(S);
  374.     Inc(LineCount);
  375.     end;
  376.   Close(F);
  377.   end;
  378.  
  379.  
  380.  
  381.  
  382.  
  383. constructor TDemoWindow.Init(WindowNo: Integer);
  384.   var  LInterior, RInterior: PInterior;
  385.        HScrollbar, VScrollbar: PScrollbar;
  386.        R: TRect;
  387.        Center: integer;
  388.  
  389.   begin
  390.     R.Assign(0,0,40,15);
  391.     R.Move(Random(40),Random(8));
  392.  
  393.     TWindow.Init(R, 'Window', wnNoNumber);
  394.     GetExtent(R);
  395.     Center:= (R.B.X + R.A.X) div 2;
  396.     R.Assign(Center,R.A.Y+1,Center+1,R.B.Y-1);
  397.     VScrollbar:= new(PScrollbar, Init(R));
  398.     with VScrollbar^ do Options := Options or ofPostProcess;
  399.     Insert(VScrollbar);
  400.     GetExtent(R);
  401.     R.Assign(R.A.X+2,R.B.Y-1,Center-1,R.B.Y);
  402.     HScrollbar:= new(PScrollbar, Init(R));
  403.     with HScrollbar^ do Options := Options or ofPostProcess;
  404.     Insert(HScrollbar);
  405.     GetExtent(R);
  406.     R.Assign(R.A.X+1,R.A.Y+1,Center,R.B.Y-1);
  407.     LInterior:= new(PInterior, Init(R, HScrollbar, VScrollbar));
  408.     with LInterior^ do
  409.       begin
  410.       Options:= Options or ofFramed;
  411.       Growmode:= GrowMode or gfGrowHiX;
  412.       SetLimit(128,LineCount);
  413.       end;
  414.     Insert(LInterior);
  415.  
  416.     GetExtent(R);
  417.     R.Assign(R.B.X-1,R.A.Y+1,R.B.X,R.B.Y-1);
  418.     VScrollbar:= new(PScrollbar, Init(R));
  419.     with VScrollbar^ do Options := Options or ofPostProcess;
  420.     Insert(VScrollbar);
  421.     GetExtent(R);
  422.     R.Assign(Center+2,R.B.Y-1,R.B.X-2,R.B.Y);
  423.     HScrollbar:= new(PScrollbar, Init(R));
  424.     with HScrollbar^ do
  425.       begin
  426.       Options := Options or ofPostProcess;
  427.       GrowMode:= GrowMode or gfGrowLoX;
  428.       end;
  429.     Insert(HScrollbar);
  430.     GetExtent(R);
  431.     R.Assign(Center+1,R.A.Y+1,R.B.X-1,R.B.Y-1);
  432.     RInterior:= new(PInterior, Init(R, HScrollbar, VScrollbar));
  433.     with RInterior^ do
  434.       begin
  435.       Options:= Options or ofFramed;
  436.       Growmode:= GrowMode or gfGrowLoX;
  437.       SetLimit(128,LineCount);
  438.       end;
  439.     Insert(RInterior);
  440.     end;
  441.  
  442.  
  443.  
  444.  
  445. procedure TMyApp.InitStatusLine;
  446.   var R: TRect;
  447.  
  448.   begin
  449.   GetExtent(R);      { find out how big the current view is }
  450.   R.A.Y := R.B.Y-1;  { squeeze R down to one line at bottom of frame }
  451.   StatusLine := New(PStatusline, Init(R,
  452.                   NewStatusDef(0, $FFFF,
  453.                     NewStatusKey('~Alt-X~ Exit', kbAltX, cmQuit,
  454.                     NewStatusKey('~F4~ New', kbF4, cmNewWin,
  455.                     NewStatusKey('~Alt-F3~ Close', kbAltF3, cmClose,
  456.                     nil))),
  457.                   nil)
  458.                 ));
  459.   end;
  460.  
  461.  
  462. { *** The vvv below indicate the primary hook-up point for the menubar-clock.
  463.   This programmer-defined normal menu structure will be tacked onto the
  464.   end of the clock menubar in TClockMenu.Init.
  465. }
  466.  
  467. procedure TMyApp.InitMenuBar;
  468.   var R: TRect;
  469.  
  470.   begin
  471.   GetExtent(R);       {***}
  472.   r.b.y:= r.a.y+1;   { vvv }
  473.   Menubar := New(PClockMenu, Init(R, NewMenu(
  474.                NewSubMenu('~F~ile', hcNoContext, NewMenu(
  475.                  NewItem('~O~pen','F3', kbF3, cmFileOpen, hcNoContext,
  476.                  NewItem('~N~ew','F4', kbF4, cmNewWin, hcNoContext,
  477.                  NewLine(
  478.                  NewItem('E~x~it','Alt-X', kbAltX, cmQuit, hcNoContext,
  479.                  nil))))),
  480.                NewSubMenu('~W~indow', hcNoContext, NewMenu(
  481.                  NewItem('~N~ext','F6', kbF6, cmNext, hcNoContext,
  482.                  NewItem('~Z~oom','F7', kbF7, cmZoom, hcNoContext,
  483.                  nil))),
  484.                nil))    { one ) for each menu defined }
  485.              )));
  486.   end;
  487.  
  488.  
  489. procedure TMyApp.NewWindow;
  490.   var
  491.     Window: PDemoWindow;
  492.     R: TRect;
  493.  
  494.   begin
  495.   inc(WinCount);
  496.   Window:= New(PDemoWindow, Init(WinCount));
  497.   Desktop^.Insert(Window);
  498.   end;
  499.  
  500.  
  501.  
  502.  
  503. {*** clock hook-up point - typecasting required to access "new" method }
  504.  
  505. procedure TMyApp.Idle;
  506.   begin
  507.   TApplication.Idle;
  508.   PClockMenu(MenuBar)^.Update;
  509.   end;
  510.  
  511.  
  512.  
  513.  
  514. procedure TMyApp.HandleEvent( var Event: TEvent);
  515.   begin
  516.   TApplication.HandleEvent(Event);
  517.   if Event.What = evCommand then
  518.     begin
  519.       case Event.Command of
  520.         cmNewWin: NewWindow;
  521.       else  { case }
  522.         Exit;
  523.       end;  { case }
  524.       ClearEvent(Event);
  525.     end; {if}
  526.   end;
  527.  
  528.  
  529.  
  530.  
  531.  
  532.  
  533.  
  534.  
  535. begin
  536.  
  537. readfile;
  538.  
  539. MyApp.Init;
  540. MyApp.run;
  541. MyApp.done;
  542. end.
  543.